package com.hama.iotrust.ws.ext;

import java.util.List;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;


@Provider
public class APIExceptionMapper implements ExceptionMapper<Exception> {

    @Context
    private HttpHeaders headers;

    private static MediaType[]    ACCEPTABLE_MEDIATYPES = {
                            MediaType.APPLICATION_JSON_TYPE,
                            MediaType.APPLICATION_XML_TYPE,
                            MediaType.TEXT_XML_TYPE,
                            MediaType.valueOf("text/json")
                        };

    private boolean isMediaTypeAcceptable(MediaType mediaType){
        if (mediaType != null){
            for (MediaType m:ACCEPTABLE_MEDIATYPES){
                if (m.getType().equalsIgnoreCase(mediaType.getType()) && m.getSubtype().equalsIgnoreCase(mediaType.getSubtype())){
                    return true;
                }
            }
        }
        return false;
    }

    public Response toResponse(Exception exception) {
        ErrorResponse er = new ErrorResponse();
        if (exception instanceof WebApplicationException){
            WebApplicationException wae = (WebApplicationException) exception;
            er.setCode(String.valueOf(wae.getResponse().getStatus()));
        } else if (exception instanceof APIServiceException){
            APIServiceException se = (APIServiceException) exception;
            er.setCode(se.getCode());
        } else {
            er.setCode(ErrorCode.SYSTEM_ERROR);
        }

        er.setMessage(exception.getMessage());

        ResponseBuilder rb = Response.status(Status.OK).entity(er);

        MediaType mediaType = null;
        List<MediaType> accepts = headers.getAcceptableMediaTypes();
        if (accepts != null && accepts.size() > 0) {
            for (MediaType m : accepts) {
                if (isMediaTypeAcceptable(m)) {
                    mediaType = m;
                    break;
                }
            }
        }
        if (mediaType == null) {
            mediaType = MediaType.APPLICATION_JSON_TYPE;
        }
        return rb.type(mediaType).build();
    }
}
